home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / dev / lang / python020.lha / python / lib / posixpath.py < prev    next >
Text File  |  1995-10-22  |  7KB  |  307 lines

  1. # Module 'posixpath' -- common operations on POSIX pathnames
  2.  
  3. import posix
  4. import stat
  5.  
  6.  
  7. # Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac.
  8. # On MS-DOS this may also turn slashes into backslashes; however, other
  9. # normalizations (such as optimizing '../' away) are not allowed
  10. # (another function should be defined to do that).
  11.  
  12. def normcase(s):
  13.     return s
  14.  
  15.  
  16. # Return wheter a path is absolute.
  17. # Trivial in Posix, harder on the Mac or MS-DOS.
  18.  
  19. def isabs(s):
  20.     return s[:1] == '/'
  21.  
  22.  
  23. # Join two pathnames.
  24. # Ignore the first part if the second part is absolute.
  25. # Insert a '/' unless the first part is empty or already ends in '/'.
  26.  
  27. def join(a, b):
  28.     if b[:1] == '/': return b
  29.     if a == '' or a[-1:] == '/': return a + b
  30.     # Note: join('x', '') returns 'x/'; is this what we want?
  31.     return a + '/' + b
  32.  
  33.  
  34. # Split a path in head (everything up to the last '/') and tail (the
  35. # rest).  If the path ends in '/', tail will be empty.  If there is no
  36. # '/' in the path, head  will be empty.
  37. # Trailing '/'es are stripped from head unless it is the root.
  38.  
  39. def split(p):
  40.     import string
  41.     i = string.rfind(p, '/') + 1
  42.     head, tail = p[:i], p[i:]
  43.     if head and head <> '/'*len(head):
  44.         while head[-1] == '/':
  45.             head = head[:-1]
  46.     return head, tail
  47.  
  48.  
  49. # Split a path in root and extension.
  50. # The extension is everything starting at the first dot in the last
  51. # pathname component; the root is everything before that.
  52. # It is always true that root + ext == p.
  53.  
  54. def splitext(p):
  55.     root, ext = '', ''
  56.     for c in p:
  57.         if c == '/':
  58.             root, ext = root + ext + c, ''
  59.         elif c == '.':
  60.             if ext:
  61.                 root, ext = root + ext, c
  62.             else:
  63.                 ext = c
  64.         elif ext:
  65.             ext = ext + c
  66.         else:
  67.             root = root + c
  68.     return root, ext
  69.  
  70.  
  71. # Split a pathname into a drive specification and the rest of the
  72. # path.  Useful on DOS/Windows/NT; on Unix, the drive is always empty.
  73.  
  74. def splitdrive(p):
  75.     return '', p
  76.  
  77.  
  78. # Return the tail (basename) part of a path.
  79.  
  80. def basename(p):
  81.     return split(p)[1]
  82.  
  83.  
  84. # Return the head (dirname) part of a path.
  85.  
  86. def dirname(p):
  87.     return split(p)[0]
  88.  
  89.  
  90. # Return the longest prefix of all list elements.
  91.  
  92. def commonprefix(m):
  93.     if not m: return ''
  94.     prefix = m[0]
  95.     for item in m:
  96.         for i in range(len(prefix)):
  97.             if prefix[:i+1] <> item[:i+1]:
  98.                 prefix = prefix[:i]
  99.                 if i == 0: return ''
  100.                 break
  101.     return prefix
  102.  
  103.  
  104. # Is a path a symbolic link?
  105. # This will always return false on systems where posix.lstat doesn't exist.
  106.  
  107. def islink(path):
  108.     try:
  109.         st = posix.lstat(path)
  110.     except (posix.error, AttributeError):
  111.         return 0
  112.     return stat.S_ISLNK(st[stat.ST_MODE])
  113.  
  114.  
  115. # Does a path exist?
  116. # This is false for dangling symbolic links.
  117.  
  118. def exists(path):
  119.     try:
  120.         st = posix.stat(path)
  121.     except posix.error:
  122.         return 0
  123.     return 1
  124.  
  125.  
  126. # Is a path a posix directory?
  127. # This follows symbolic links, so both islink() and isdir() can be true
  128. # for the same path.
  129.  
  130. def isdir(path):
  131.     try:
  132.         st = posix.stat(path)
  133.     except posix.error:
  134.         return 0
  135.     return stat.S_ISDIR(st[stat.ST_MODE])
  136.  
  137.  
  138. # Is a path a regular file?
  139. # This follows symbolic links, so both islink() and isfile() can be true
  140. # for the same path.
  141.  
  142. def isfile(path):
  143.     try:
  144.         st = posix.stat(path)
  145.     except posix.error:
  146.         return 0
  147.     return stat.S_ISREG(st[stat.ST_MODE])
  148.  
  149.  
  150. # Are two filenames really pointing to the same file?
  151.  
  152. def samefile(f1, f2):
  153.     s1 = posix.stat(f1)
  154.     s2 = posix.stat(f2)
  155.     return samestat(s1, s2)
  156.  
  157.  
  158. # Are two open files really referencing the same file?
  159. # (Not necessarily the same file descriptor!)
  160. # XXX Oops, posix.fstat() doesn't exist yet!
  161.  
  162. def sameopenfile(fp1, fp2):
  163.     s1 = posix.fstat(fp1)
  164.     s2 = posix.fstat(fp2)
  165.     return samestat(s1, s2)
  166.  
  167.  
  168. # Are two stat buffers (obtained from stat, fstat or lstat)
  169. # describing the same file?
  170.  
  171. def samestat(s1, s2):
  172.     return s1[stat.ST_INO] == s2[stat.ST_INO] and \
  173.         s1[stat.ST_DEV] == s2[stat.ST_DEV]
  174.  
  175.  
  176. # Is a path a mount point?
  177. # (Does this work for all UNIXes?  Is it even guaranteed to work by POSIX?)
  178.  
  179. def ismount(path):
  180.     try:
  181.         s1 = posix.stat(path)
  182.         s2 = posix.stat(join(path, '..'))
  183.     except posix.error:
  184.         return 0 # It doesn't exist -- so not a mount point :-)
  185.     dev1 = s1[stat.ST_DEV]
  186.     dev2 = s2[stat.ST_DEV]
  187.     if dev1 != dev2:
  188.         return 1        # path/.. on a different device as path
  189.     ino1 = s1[stat.ST_INO]
  190.     ino2 = s2[stat.ST_INO]
  191.     if ino1 == ino2:
  192.         return 1        # path/.. is the same i-node as path
  193.     return 0
  194.  
  195.  
  196. # Directory tree walk.
  197. # For each directory under top (including top itself, but excluding
  198. # '.' and '..'), func(arg, dirname, filenames) is called, where
  199. # dirname is the name of the directory and filenames is the list
  200. # files files (and subdirectories etc.) in the directory.
  201. # The func may modify the filenames list, to implement a filter,
  202. # or to impose a different order of visiting.
  203.  
  204. def walk(top, func, arg):
  205.     try:
  206.         names = posix.listdir(top)
  207.     except posix.error:
  208.         return
  209.     func(arg, top, names)
  210.     exceptions = ('.', '..')
  211.     for name in names:
  212.         if name not in exceptions:
  213.             name = join(top, name)
  214.             if isdir(name) and not islink(name):
  215.                 walk(name, func, arg)
  216.  
  217.  
  218. # Expand paths beginning with '~' or '~user'.
  219. # '~' means $HOME; '~user' means that user's home directory.
  220. # If the path doesn't begin with '~', or if the user or $HOME is unknown,
  221. # the path is returned unchanged (leaving error reporting to whatever
  222. # function is called with the expanded path as argument).
  223. # See also module 'glob' for expansion of *, ? and [...] in pathnames.
  224. # (A function should also be defined to do full *sh-style environment
  225. # variable expansion.)
  226.  
  227. def expanduser(path):
  228.     if path[:1] <> '~':
  229.         return path
  230.     i, n = 1, len(path)
  231.     while i < n and path[i] <> '/':
  232.         i = i+1
  233.     if i == 1:
  234.         if not posix.environ.has_key('HOME'):
  235.             return path
  236.         userhome = posix.environ['HOME']
  237.     else:
  238.         import pwd
  239.         try:
  240.             pwent = pwd.getpwnam(path[1:i])
  241.         except KeyError:
  242.             return path
  243.         userhome = pwent[5]
  244.     return userhome + path[i:]
  245.  
  246.  
  247. # Expand paths containing shell variable substitutions.
  248. # This expands the forms $variable and ${variable} only.
  249. # Non-existant variables are left unchanged.
  250.  
  251. _varprog = None
  252.  
  253. def expandvars(path):
  254.     global _varprog
  255.     if '$' not in path:
  256.         return path
  257.     if not _varprog:
  258.         import regex
  259.         _varprog = regex.compile('$\([a-zA-Z0-9_]+\|{[^}]*}\)')
  260.     i = 0
  261.     while 1:
  262.         i = _varprog.search(path, i)
  263.         if i < 0:
  264.             break
  265.         name = _varprog.group(1)
  266.         j = i + len(_varprog.group(0))
  267.         if name[:1] == '{' and name[-1:] == '}':
  268.             name = name[1:-1]
  269.         if posix.environ.has_key(name):
  270.             tail = path[j:]
  271.             path = path[:i] + posix.environ[name]
  272.             i = len(path)
  273.             path = path + tail
  274.         else:
  275.             i = j
  276.     return path
  277.  
  278.  
  279. # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
  280. # It should be understood that this may change the meaning of the path
  281. # if it contains symbolic links!
  282.  
  283. def normpath(path):
  284.     import string
  285.     # Treat initial slashes specially
  286.     slashes = ''
  287.     while path[:1] == '/':
  288.         slashes = slashes + '/'
  289.         path = path[1:]
  290.     comps = string.splitfields(path, '/')
  291.     i = 0
  292.     while i < len(comps):
  293.         if comps[i] == '.':
  294.             del comps[i]
  295.         elif comps[i] == '..' and i > 0 and \
  296.                       comps[i-1] not in ('', '..'):
  297.             del comps[i-1:i+1]
  298.             i = i-1
  299.         elif comps[i] == '' and i > 0 and comps[i-1] <> '':
  300.             del comps[i]
  301.         else:
  302.             i = i+1
  303.     # If the path is now empty, substitute '.'
  304.     if not comps and not slashes:
  305.         comps.append('.')
  306.     return slashes + string.joinfields(comps, '/')
  307.